package com.scs.application.modules.msg.ram;

import org.apache.poi.ss.formula.functions.T;

import java.io.*;
import java.util.Iterator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;

/**
 */
public class LesonQueueBuilder<E> {
    public volatile static LesonQueueBuilder queueBuilder = null;

    // 状态字段
    public static final int save = 1;
    public static final int nosave = 0;

    //即可写到磁盘
    public static boolean timeSave = false;

    //存储文件后缀
    public final String SUFFIX = ".lmq";
    public String queueName = null;
    public String home = LesonQueueBuilder.class.getResource("/").getPath() + "MQ/";
    public File file = null;
    private ConcurrentHashMap<String, LesonQueue<E>> a = new ConcurrentHashMap<String, LesonQueue<E>>();

    private LesonQueueBuilder() {
    }

    public static LesonQueueBuilder builder(Class<?> c, String queueName, int save) {
        if (queueBuilder == null) {
            synchronized (LesonQueueBuilder.class) {
                if (queueBuilder == null)
                    queueBuilder =  new LesonQueueBuilder<T>();
                    queueBuilder.build();
            }
        }

        if (queueBuilder != null) {

            if (save == save) {
                LesonQueueBuilder.timeSave = true;
            }
            queueBuilder.builder(queueName);
        }
        return queueBuilder;
    }

    private void builder(String queueName) {

        if (queueName == null || "".equals(queueName)) {
            throw new RuntimeException(" queueName 不能为空！");
        }

        String path = home + queueName + SUFFIX;
        this.file = new File(path);
        if (!this.file.getParentFile().exists()) {
            this.file.getParentFile().mkdirs();
        }
        this.queueName = queueName;
        if (!a.containsKey(queueName))
            a.put(queueName, new LesonQueue<E>());

    }

    private void build() {
        File file = new File(this.home);
        if (file.isDirectory()) {
            String[] list = file.list();
            for (String fileName : list) {
                if (fileName.endsWith(this.SUFFIX)) {
                    String path = this.home + fileName;
                    BlockingQueue<E> store = synRead(path);
                    a.put(fileName.substring(0, fileName.indexOf(this.SUFFIX)), new LesonQueue<E>(store));
                }
            }
        }
    }

    public void put(E e) {
        LesonQueue queue = a.get(queueName);
        if(!queue.store.contains(e)) {
            if (queue.store.offer(e)) {
                if (LesonQueueBuilder.timeSave) asynWrite(queue);
            } else
                throw new RuntimeException("队列最大容量 " + queue.MAX_VALUE + " 当前容量 " + queue.store.size());
        }
    }

    public E get() {
        LesonQueue queue = a.get(queueName);
        E peek = (E) queue.store.peek();

        if (peek == null) {
            BlockingQueue<E> store = synRead(file.getPath());
            peek = store.peek();
        }
        return peek;
    }

    public void remove(E e) {
        LesonQueue queue = a.get(queueName);
        if (queue.store.contains(e)) {
            queue.store.remove(e);
            if (LesonQueueBuilder.timeSave) asynWrite(queue);
        }
    }

    public Iterator<E> iterable(){
        LesonQueue<E> queue = a.get(queueName);
        return queue.store.iterator();
    }
    /**
     * 返回队列的第一个元素并删除
     *
     * @return
     * @throws InterruptedException
     */
    public E poll() throws InterruptedException {
        LesonQueue queue = a.get(queueName);
        E e = (E) queue.store.take();
        if (LesonQueueBuilder.timeSave) asynWrite(queue);
        return e;
    }

    /**
     * 异步写入到磁盘
     *
     * @param queue
     */
    public void asynWrite(LesonQueue queue) {
        // 异步写入磁盘
        new Thread(new Runnable() {
            @Override
            public void run() {
                synWrite(queue);
            }
        }).start();
    }

    /**
     * 写入到磁盘
     *
     * @param queue
     */
    public void synWrite(LesonQueue queue) {
        FileOutputStream fos = null;
        ObjectOutputStream oos = null;
        try {
            fos = new FileOutputStream(this.file);
            oos = new ObjectOutputStream(fos);
            oos.writeObject(queue.store);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (fos != null)
                    fos.close();
                if (oos != null)
                    oos.close();
            } catch (Exception ex) {
            }
        }
    }

    /**
     * 读取磁盘
     *
     * @return
     */
    public BlockingQueue<E> synRead(String path) {
        FileInputStream fis = null;
        ObjectInputStream ois = null;
        try {
            fis = new FileInputStream(path);
            ois = new ObjectInputStream(fis);
            BlockingQueue<E> s = (BlockingQueue<E>) ois.readObject();
            return s;
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (fis != null)
                    fis.close();
                if (ois != null)
                    ois.close();
            } catch (Exception ex) {
            }
        }
        return null;
    }

}
